﻿using System;
using Microsoft.Silverlight.Testing;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SilverMindMap.Core.Model;
using SilverMindMap.Core.Tests.TestHelpers;

namespace SilverMindMap.Core.Tests.Model
{
    [TestClass]
    public class MindMapTests
    {
        [TestMethod]
        [Tag(TestTags.BVT)]
        public void AddNodeTest()
        {
            var mindMap = new MindMap();
            
            var node1 = new Node();
            var node2 = new Node();
            node1.AddLink(node2);

            mindMap.AddNode(node1);
            Assert.IsTrue(mindMap.Nodes.Contains(node1));
            Assert.IsFalse(mindMap.Nodes.Contains(node2));
            Assert.AreSame(mindMap, node1.MindMap);

            mindMap.AddNode(node2);
            Assert.IsTrue(mindMap.Nodes.Contains(node2));
            Assert.AreSame(mindMap, node2.MindMap);
        }

        [TestMethod]
        public void AddNodeFromDifferentMinMapTest()
        {
            var mindMap1 = new MindMap();
            var mindMap2 = new MindMap();

            var node = new Node();

            mindMap1.AddNode(node);
            mindMap2.AddNode(node);

            Assert.AreSame(mindMap2, node.MindMap);
            Assert.IsFalse(mindMap1.Nodes.Contains(node));
            Assert.IsTrue(mindMap2.Nodes.Contains(node));
        }

        [TestMethod]
        [Tag(TestTags.BVT)]
        public void RemoveNodeTest()
        {
            var mindMap = new MindMap();
            var node1 = new Node();
            var node2 = new Node();

            mindMap.AddNode(node1);
            mindMap.AddNode(node2);

            // Removing node1
            Assert.IsTrue(mindMap.RemoveNode(node1));
            Assert.IsFalse(mindMap.Nodes.Contains(node1));
            Assert.IsTrue(mindMap.Nodes.Contains(node2));
            Assert.IsNull(node1.MindMap);

            // Trying to remove node1 again.
            Assert.IsFalse(mindMap.RemoveNode(node1));

            // Removing node2
            Assert.IsTrue(mindMap.RemoveNode(node2));
            Assert.IsFalse(mindMap.Nodes.Contains(node2));
            Assert.IsNull(node2.MindMap);

        }

        [TestMethod]
        [Tag(TestTags.BVT)]
        public void SetRootNodeToValidNodeTest()
        {
            var mindMap = new MindMap();
            var node1 = new Node();
            var node2 = new Node();

            mindMap.AddNode(node1);
            mindMap.AddNode(node2);

            Assert.IsNull(mindMap.RootNode, "Invalid initial value of root node");

            mindMap.RootNode = node1;
            Assert.AreSame(node1, mindMap.RootNode);

            mindMap.RootNode = node2;
            Assert.AreSame(node2, mindMap.RootNode);
        }

        [TestMethod]
        public void SetRootNodeToExternalNodeTest()
        {
            var mindMap = new MindMap();
            var node = new Node();

            ExceptionAssert.Thrown(
                () => mindMap.RootNode = node,
                e => e is ArgumentException,
                "Setting RootNode to external node should cause ArgumentException");
        }

        [TestMethod]
        public void SetRootNodeNotificationTest()
        {
            var mindMap = new MindMap();
            var node = new Node();
            mindMap.AddNode(node);

            int changedPropertyNotificationsCount = 0;
            string changedPropertyName = null;
            Node changedProeprtyValue = null;

            mindMap.PropertyChanged += (s, a) =>
                {
                    changedPropertyNotificationsCount++;
                    changedPropertyName = a.PropertyName;
                    changedProeprtyValue = mindMap.RootNode;
                };

            mindMap.RootNode = node;
            Assert.AreEqual(1, changedPropertyNotificationsCount);
            Assert.AreEqual("RootNode", changedPropertyName);
            Assert.AreSame(node, changedProeprtyValue);
        }
    }
}
